/**********************************************************
 * Author    : Riwut Libinuko (cakriwut@gmail.com)
 * Blog      : http://blog.libinuko.com
 * Copyright : Riwut Libinuko (c) 2009 - 2010
 * 
 **********************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using IdeasFree.SharePoint.ScheduleReminder.Helper;

namespace IdeasFree.SharePoint.ScheduleReminder.EventReceiver
{
    /// <summary>
    /// Edit series => ListItemID = RecurrenceID , example 19
    /// Edit item in series => ListItemID != RecurrenceID , example , 47.1.19
    /// </summary>
    public class CalendarEventReceiver : SPItemEventReceiver
    {
        private static string NotifyListName = "_x_notify_";
        // Check for notification on added, updated
        public override void ItemAdded(SPItemEventProperties properties)
        {
            base.ItemAdded(properties);
            CheckItem(properties);
           // SetItemLevelSecurity(properties);
            
        }

        public override void ItemUpdated(SPItemEventProperties properties)
        {
            base.ItemUpdated(properties);
            CheckItem(properties);
        }

        private void SetItemLevelSecurity(SPItemEventProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPWeb eventWeb = new SPSite(properties.WebUrl).OpenWeb())
                {
                    SPRoleDefinition roleAdminDef = eventWeb.RoleDefinitions.GetByType(SPRoleType.Administrator);
                    SPListItem item = eventWeb.Lists[properties.ListId].GetItemById(properties.ListItemId);
                    item.BreakRoleInheritance(true);
                    SPRoleAssignmentCollection roleAssigns = item.RoleAssignments;
                    for (int i = roleAssigns.Count - 1; i >= 0; i--)
                        if (!roleAssigns[i].RoleDefinitionBindings.Contains(roleAdminDef))
                            roleAssigns.Remove(i);

                    string authorIDstring = item[Consts.AuthorField].ToString().Substring(0, item[Consts.AuthorField].ToString().IndexOf(";#"));
                    int authorID;

                    if (int.TryParse(authorIDstring, out authorID))
                    {
                        SPUser user = eventWeb.SiteUsers.GetByID(authorID);
                        SPRoleDefinition roleContributorDef = eventWeb.RoleDefinitions.GetByType(SPRoleType.Contributor);
                        SPRoleAssignment roleAssignment = new SPRoleAssignment(user.LoginName,
                            string.Empty, string.Empty, string.Empty);
                        roleAssignment.RoleDefinitionBindings.Add(roleContributorDef);
                        roleAssigns.Add(roleAssignment);
                    }

                }

            });
        }


        // Delete notification on deleted
        public override void ItemDeleted(SPItemEventProperties properties)
        {
            
            using (SPWeb eventWeb = properties.OpenWeb())
            {
                SPList notifyList;
                try
                {
                    notifyList = eventWeb.Lists[NotifyListName];
                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("<Where><And>"+
                        "<Eq><FieldRef Name='ListItemID' /><Value Type='Text'>{0}</Value></Eq>" +
                        "<Eq><FieldRef Name='Title' /><Value Type='Text'>{1}</Value></Eq>" +
                        "</And></Where>",properties.ListItemId,properties.ListId.ToString());
                    SPQuery query = new SPQuery();
                    query.Query = sb.ToString();

                    foreach (SPListItem item in notifyList.GetItems(query))
                        item.Delete();
                }
                catch { }
            }
            base.ItemDeleted(properties);
        }

        private bool CheckItem(SPItemEventProperties properties)
        {
            // Skip if not editing series , because we will skip email notification on the scheduleAlertJob
            //if (!properties.ListItemId.ToString().Equals(properties.ListItem.RecurrenceID))
            //    return true;

            using (SPWeb eventWeb = properties.OpenWeb())
            {

                SPList notifyList;
                try
                {
                    notifyList = eventWeb.Lists[NotifyListName];
                }
                catch
                {
                    Guid listGUID = eventWeb.Lists.Add(NotifyListName, "Notify List Name", SPListTemplateType.GenericList);
                    notifyList = eventWeb.Lists[listGUID];
                    notifyList.Fields.Add(Consts.EstTimetoSendField, SPFieldType.DateTime, false);
                    notifyList.Fields.Add(Consts.ActTimetoSendField, SPFieldType.DateTime, false);
                    notifyList.Fields.Add(Consts.ListItemIDField, SPFieldType.Text, false);
#if !DEBUG
                    notifyList.Hidden = true;
#endif
                    notifyList.Update();

                }
                if (notifyList == null)
                {
                    return false;
                }
                bool enableReminder = false;
                bool.TryParse(properties.AfterProperties["EnableReminder"].ToString(), out enableReminder);


                SPListItem item;

                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("<Where><And>" +
                    "<Eq><FieldRef Name='ListItemID' /><Value Type='Text'>{0}</Value></Eq>" +
                    "<Eq><FieldRef Name='Title' /><Value Type='Text'>{1}</Value></Eq>" +
                    "</And></Where>", properties.ListItemId, properties.ListId.ToString());
                SPQuery query = new SPQuery();
                query.Query = sb.ToString();

                SPListItemCollection items = notifyList.GetItems(query);
                if (items.Count > 0)
                {
                    item = items[0];
                    if (!enableReminder)
                    {
                        item.Delete();
                        return true;
                    }

                }
                else if (enableReminder)
                    item = notifyList.Items.Add();
                else
                    return true;

                // Query the recurrence
                StringBuilder sbEvent = new StringBuilder();  // Prepare query to the calendar
                sbEvent.AppendFormat("<Where>" +
                    "<And>" +
                    "<Eq><FieldRef Name='ID' /><Value Type='Int'>{0}</Value></Eq>" +
                    "<DateRangesOverlap>" +
                          "<FieldRef Name='EventDate' /><FieldRef Name='EndDate' />" +
                          "<FieldRef Name='RecurrenceID' /><Value Type='DateTime'><Year   /></Value>" +
                    "</DateRangesOverlap>" +
                    "</And>" +
                    "</Where>", properties.ListItemId.ToString());

                SPQuery qry = new SPQuery();
                qry.ExpandRecurrence = true;
                qry.Query = sbEvent.ToString();

                SPList calendarList = properties.OpenWeb().Lists[properties.ListId];
                SPListItemCollection calendarItems = calendarList.GetItems(qry);

                if (calendarItems.Count <= 0)
                    return false;
                else
                {
                    foreach (SPListItem calendarItem in calendarItems)
                    {
                        string[] reminderTimeCollection = calendarItem[Consts.ReminderField].ToString().Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries);
                        SPTimeZone tZone = eventWeb.RegionalSettings.TimeZone;
                        DateTime etsDate = (DateTime)calendarItem[Consts.EventDateField];// SPUtility.CreateDateTimeFromISO8601DateTimeString(calendarItem[Consts.EventDateField].ToString());
                        List<DateTime> reminderDateList = Utility.CalculateDate(etsDate, reminderTimeCollection);

                        if (reminderDateList.Exists(Utility.DateGreaterThanToday))
                        {
                            item[Consts.TitleField] = properties.ListId.ToString();
                            item[Consts.ListItemIDField] = properties.ListItemId.ToString();
                            item[Consts.EstTimetoSendField] = reminderDateList.Find(Utility.DateGreaterThanToday);
                            item.Update();
                        }
                        else
                        {
                            continue;
                        }
                    }
                    return true;
                }
            }            
        }
    }
}
